package com.ipc.app.biz.impl;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import com.ipc.app.biz.OrderBiz;
import com.ipc.app.constants.OrderStatusConstants;
import com.ipc.app.model.Information;
import com.ipc.app.model.Order;
import com.ipc.app.model.Paginator;
import com.ipc.app.model.User;
import com.ipc.app.service.InformationService;
import com.ipc.app.service.OrderService;

/**
 * @author 雪
 * 
 */
public class OrderBizImpl implements OrderBiz {

	private InformationService informationService;

	private OrderService orderService;

	private TransactionTemplate transactionTemplate;

	public Order bookSeat(final String informationId, final String userID) {

		transactionTemplate
				.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
		Order order = (Order) transactionTemplate
				.execute(new TransactionCallback() {

					public Object doInTransaction(TransactionStatus arg0) {
						Information information = informationService
								.lockInformation(informationId);
						// TODO:剩余座位检测
						if (!ifSeatAvaliable(information)) {
							return null;
						}

						Order order = new Order();
						order.setInformation(information);

						// TODO:付款金额方式
						Integer payAmount = information.getPrice();
						order.setPayAmount(payAmount);

						// TODO:是否需要用户其他信息，或者用户模型是否需要更改
						User user = new User();
						user.setUserId(userID);
						order.setUser(user);

						// TODO:付款信息
						order.setStatus(OrderStatusConstants.BOOKED_AND_PAID);
						updateInformationBookedSeat(information);

						// 如果需要支付金额为0，则直接将状态置为已支付
						/*
						 * if (0 == payAmount) { order
						 * .setStatus(OrderStatusConstants.BOOKED_AND_PAID);
						 * updateInformationBookedSeat(information); } else {
						 * order
						 * .setStatus(OrderStatusConstants.BOOKED_NOT_PAY); }
						 */

						String orderId = orderService.createOrder(order);

						Order or = orderService.getOrderByID(orderId);
						return or;
					}
				});
		return order;

	}

	/**
	 * 是否有座位可以预定
	 * 
	 * @param information
	 * @return
	 */
	private boolean ifSeatAvaliable(Information information) {
		Integer seatNumber = information.getSeatNumber();
		Integer bookedSeatNumber = information.getBookedSeatNumber();
		if (bookedSeatNumber < seatNumber) {
			return true;
		}
		return false;
	}

	public List<Order> queryExpiredOrder() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY) - 2);

		Date date = cal.getTime();

		List<Order> expiredOrder = orderService.getExpiredOrder(date);

		return expiredOrder;

	}

	/**
	 * 预定座位更新
	 * 
	 * @param information
	 */
	private void updateInformationBookedSeat(Information information) {
		Integer bookedSeatNumber = information.getBookedSeatNumber();
		++bookedSeatNumber;
		information.setBookedSeatNumber(bookedSeatNumber);
		informationService.updateInformation(information);
	}

	public void setOrderExpired(final String orderID) {
		transactionTemplate
				.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus arg0) {
				Order order = orderService.lockOrder(orderID);
				if (null == order) {
					return;
				}
				String status = order.getStatus();
				if (OrderStatusConstants.BOOKED_NOT_PAY.equals(status)) {
					order.setStatus(OrderStatusConstants.EXPIRED);
					orderService.updateOrder(order);
				}
			}

		});

	}

	public Paginator<Order> getUserOrder(String userID, int pageIndex) {
		Paginator<Order> orders = orderService.getOrderByUserID(userID,
				pageIndex);
		return orders;
	}

	public void setInformationService(InformationService informationService) {
		this.informationService = informationService;
	}

	public void setOrderService(OrderService orderService) {
		this.orderService = orderService;

	}

	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
		this.transactionTemplate = transactionTemplate;
	}

}
